#ifndef TwMatrix4x4_H
#define TwMatrix4x4_H
 
 
class TwMatrix4x4 : public D3DXMATRIX
{
public:


	// Creators...

	TwMatrix4x4();
    explicit TwMatrix4x4(const TwMatrix4x4& Src);
    explicit TwMatrix4x4(const float* _16_floats);
    explicit TwMatrix4x4(float _11, float _12, float _13, float _14,
               float _21, float _22, float _23, float _24,
               float _31, float _32, float _33, float _34,
               float _41, float _42, float _43, float _44);
	~TwMatrix4x4();

	// Mutators...
	void SetIdentity();

	void Transpose();
	void Transpose(const TwMatrix4x4& matrix);
	void Transpose(const TwMatrix4x4* matrix);
	bool invert();
	bool invert( const TwMatrix4x4& matrix);
	bool invert( const TwMatrix4x4* matrix);

    void set(float _11, float _12, float _13, float _14,
               float _21, float _22, float _23, float _24,
               float _31, float _32, float _33, float _34,
               float _41, float _42, float _43, float _44);

 

	void getRow(UINT8 i, TwVector4d* pVector);

	// Accessors...

private:

	// Private Data...

	// Private Functions...

};

//- Inline Functions ---------------------------------------------------------------------

//. Creators .............................................................................

/*	TwMatrix4x4
------------------------------------------------------------------------------------------
	
	Default Constructor
	
------------------------------------------------------------------------------------------
*/
inline TwMatrix4x4::TwMatrix4x4()
{
}

/*	TwMatrix4x4(const TwMatrix4x4& Src)
------------------------------------------------------------------------------------------
	
	Copy Constructor
	
------------------------------------------------------------------------------------------
*/
inline TwMatrix4x4::TwMatrix4x4(const TwMatrix4x4& Src)
:D3DXMATRIX((const D3DXMATRIX&) Src)
{
}

inline TwMatrix4x4::TwMatrix4x4(const float* _16_floats)
:D3DXMATRIX((FLOAT*) _16_floats)
{
}

inline TwMatrix4x4::TwMatrix4x4(float _11, float _12, float _13, float _14,
            float _21, float _22, float _23, float _24,
            float _31, float _32, float _33, float _34,
            float _41, float _42, float _43, float _44)
:D3DXMATRIX(_11, _12, _13, _14,
            _21, _22, _23, _24,
            _31, _32, _33, _34,
            _41, _42, _43, _44)
{
}

/*	~TwMatrix4x4
------------------------------------------------------------------------------------------
	
	Default Destructor
	
------------------------------------------------------------------------------------------
*/
inline TwMatrix4x4::~TwMatrix4x4()
{
}


/*	Casting Operators
------------------------------------------------------------------------------------------
	
	Cast this type to any of the types provided below
	
------------------------------------------------------------------------------------------
*/

//. Mutators .............................................................................


/*	SetIdentity()
------------------------------------------------------------------------------------------
	
	set this matrix to the identity matrix.
	
------------------------------------------------------------------------------------------
*/
inline void TwMatrix4x4::SetIdentity()
{
	D3DXMatrixIdentity(this);
}

inline void TwMatrix4x4::set(
	float m11, float m12, float m13, float m14,
	float m21, float m22, float m23, float m24,
	float m31, float m32, float m33, float m34,
	float m41, float m42, float m43, float m44)
{
	_11 = m11;
	_12 = m12;
	_13 = m13;
	_14 = m14;
	_21 = m21;
	_22 = m22;
	_23 = m23;
	_24 = m24;
	_31 = m31;
	_32 = m32;
	_33 = m33;
	_34 = m34;
	_41 = m41;
	_42 = m42;
	_43 = m43;
	_44 = m44;
}

/*	SetTranslation(float x, float y, float z)
------------------------------------------------------------------------------------------
	
	set this matrix to the translation parameters provided.
	
------------------------------------------------------------------------------------------
*/
/*
inline void TwMatrix4x4::SetTranslation(float x, float y, float z)
{
	D3DXMatrixTranslation(this, x, y, z);
}

inline void TwMatrix4x4::SetTranslation(const TwVector3d& vec)
{
	D3DXMatrixTranslation(this, vec.x, vec.y, vec.z);
}

inline void TwMatrix4x4::SetTranslation(const TwVector4d& vec)
{
	D3DXMatrixTranslation(this, vec.x, vec.y, vec.z);
}

inline void TwMatrix4x4::SetTranslation(const TwVector3d* vec)
{
	D3DXMatrixTranslation(this, vec->x, vec->y, vec->z);
}

inline void TwMatrix4x4::SetTranslation(const TwVector4d* vec)
{
	D3DXMatrixTranslation(this, vec->x, vec->y, vec->z);
}
*/

/*	SetScale(float x, float y, float z)
------------------------------------------------------------------------------------------
	
	set this matrix to the scale parameters provided.
	
------------------------------------------------------------------------------------------
*/
/*
inline void TwMatrix4x4::SetScale(float x, float y, float z)
{
	D3DXMatrixScale(this, x, y, z);
}

inline void TwMatrix4x4::SetScale(const TwVector3d& vec)
{
	D3DXMatrixScale(this, vec.x, vec.y, vec.z);
}

inline void TwMatrix4x4::SetScale(const TwVector4d& vec)
{
	D3DXMatrixScale(this, vec.x, vec.y, vec.z);
}

inline void TwMatrix4x4::SetScale(const TwVector3d* vec)
{
	D3DXMatrixScale(this, vec->x, vec->y, vec->z);
}

inline void TwMatrix4x4::SetScale(const TwVector4d* vec)
{
	D3DXMatrixScale(this, vec->x, vec->y, vec->z);
}
*/

/*	Transpose()
------------------------------------------------------------------------------------------
	
	swap the matrix members along the major diagonal.
	
------------------------------------------------------------------------------------------
*/
inline void TwMatrix4x4::Transpose()
{
	swapValue(m[0][1], m[1][0]);
	swapValue(m[0][2], m[2][0]);
	swapValue(m[0][3], m[3][0]);
	swapValue(m[1][2], m[2][1]);
	swapValue(m[1][3], m[3][1]);
	swapValue(m[2][3], m[3][2]);
}

inline void TwMatrix4x4::Transpose(const TwMatrix4x4& matrix)
{
	D3DXMatrixTranspose(this, &matrix);
}

inline void TwMatrix4x4::Transpose(const TwMatrix4x4* matrix)
{
	D3DXMatrixTranspose(this, matrix);
}

/*	invert( const TwMatrix4x4& matrix)
------------------------------------------------------------------------------------------
	
	set the local matrix to the inverted version of the provided matrix. Returns false if
	no inverse can be calculated.
	
------------------------------------------------------------------------------------------
*/
inline bool TwMatrix4x4::invert( const TwMatrix4x4& matrix)
{
	float determinant;
	return 0 != D3DXMatrixInverse(this,&determinant, &matrix);
};

inline bool TwMatrix4x4::invert( const TwMatrix4x4* matrix)
{
	float determinant;
	return 0 != D3DXMatrixInverse(this,&determinant, matrix);
}

inline bool TwMatrix4x4::invert()
{
	float determinant;
	return 0 != D3DXMatrixInverse(this,&determinant, this);
}

 
 
inline void TwMatrix4x4::getRow(UINT8 i, TwVector4d* pVector)
{
//	debug_assert(i<4, "invalid row index");

	float* pData = &_11;
	pData += i*4;

	pVector->x = pData[0];
	pVector->y = pData[1];
	pVector->z = pData[2];
	pVector->w = pData[3];

}

#define _cSIMDMatrix D3DX_ALIGN16 TwMatrix4x4
//typedef _cSIMDMatrix cSIMDMatrix;

D3DX_ALIGN16 class cSIMDMatrix : public TwMatrix4x4
{
public:


	// Creators...

	cSIMDMatrix(){};
	~cSIMDMatrix(){};
   explicit cSIMDMatrix(const cSIMDMatrix& Src);
    explicit cSIMDMatrix(const TwMatrix4x4& Src);
    explicit cSIMDMatrix(const D3DXMATRIX& Src);
    explicit cSIMDMatrix(const float* _16_floats);
    explicit cSIMDMatrix(float _11, float _12, float _13, float _14,
               float _21, float _22, float _23, float _24,
               float _31, float _32, float _33, float _34,
               float _41, float _42, float _43, float _44);

};

inline cSIMDMatrix::cSIMDMatrix(const cSIMDMatrix& Src)
:TwMatrix4x4((const TwMatrix4x4&) Src)
{
}
inline cSIMDMatrix::cSIMDMatrix(const TwMatrix4x4& Src)
:TwMatrix4x4((const TwMatrix4x4&) Src)
{
}
inline cSIMDMatrix::cSIMDMatrix(const D3DXMATRIX& Src)
:TwMatrix4x4((const TwMatrix4x4&) Src)
{
}

inline cSIMDMatrix::cSIMDMatrix(const float* _16_floats)
:TwMatrix4x4((FLOAT*) _16_floats)
{
}

inline cSIMDMatrix::cSIMDMatrix(float _11, float _12, float _13, float _14,
            float _21, float _22, float _23, float _24,
            float _31, float _32, float _33, float _34,
            float _41, float _42, float _43, float _44)
:TwMatrix4x4(_11, _12, _13, _14,
            _21, _22, _23, _24,
            _31, _32, _33, _34,
            _41, _42, _43, _44)
{
}

inline TwMatrix4x4* MatrixMultiply(TwMatrix4x4* dest, const TwMatrix4x4* src_a, const TwMatrix4x4* src_b)
{
	D3DXMatrixMultiply(dest, src_a, src_b);
	return dest;
}

 

#endif  

